package kded.demo.schedule;

import kd.bos.dataentity.serialization.SerializationUtils;
import kd.bos.dataentity.utils.StringUtils;
import kd.bos.form.CloseCallBack;
import kd.bos.form.control.Control;
import kd.bos.form.control.events.ItemClickEvent;
import kd.bos.form.events.ClosedCallBackEvent;
import kd.bos.form.plugin.AbstractFormPlugin;
import kd.bos.schedule.api.JobInfo;
import kd.bos.schedule.api.JobType;
import kd.bos.schedule.api.TaskInfo;
import kd.bos.schedule.form.JobForm;
import kd.bos.schedule.form.JobFormInfo;

import java.util.EventObject;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 任务发布界面插件
 *
 * @author rd_johnnyding
 *
 * @remark
 * 演示如何发起一个任务，并显示任务进度界面，捕获任务结束事件
 */
public class JobDispatchFormPlugin extends AbstractFormPlugin {

    private static final String KEY_JOBDISPATCH = "btnjobdispatch";

    /**
     * 添加事件监听："启动任务"按钮点击事件
     */
    @Override
    public void registerListener(EventObject e) {
        super.registerListener(e);
        this.addItemClickListeners(KEY_JOBDISPATCH,"tbmain");
        this.addClickListeners(KEY_JOBDISPATCH);
    }

    /**
     * 事件处理："启动任务"按钮点击事件
     */
    @Override
    public void click(EventObject evt) {
        Control source = (Control)evt.getSource();
        if (StringUtils.equalsIgnoreCase(KEY_JOBDISPATCH, source.getKey())) {
            this.dispatch();
        }
    }

    @Override
    public void itemClick(ItemClickEvent evt) {
        if (StringUtils.equalsIgnoreCase(KEY_JOBDISPATCH, evt.getItemKey())) {
            this.dispatch();
        }
    }

    /**
     * 回调事件，在任务处理完毕后继续后续处理
     */
    @Override
    public void closedCallBack(ClosedCallBackEvent closedCallBackEvent) {
        super.closedCallBack(closedCallBackEvent);

        if (StringUtils.equals(closedCallBackEvent.getActionId(), "taskcloseback")) {
            this.taskCallBack(closedCallBackEvent.getReturnData());
        }
    }

    /**
     * 关注点
     * 1、通过后台代码发起调度任务的方法，相当于异步，解耦，底层通过mq实现
     * 2、后台异步和界面上异步的接口参数不一样。
     * 3、界面上异步需要websocket支持。
     * 创建任务目标，发布新任务
     */
    private void dispatch() {

        // 创建任务目标
        JobInfo jobInfo = new JobInfo();
        jobInfo.setAppId("bos");                // 执行类所在的应用名
        jobInfo.setJobType(JobType.REALTIME);   // 即时执行
        jobInfo.setName("test job");
        jobInfo.setId(UUID.randomUUID().toString());        // 随机产生一个JobId (任务目标的标识)
        jobInfo.setTaskClassname("kded.demo.schedule.MyTask");

        // 自定义参数
        Map<String,Object> params = new HashMap<>();
        params.put("time", 80);         // 自定义参数，示例任务执行循环次数，80次
        jobInfo.setParams(params);

        // 回调参数，设置一个回调处理标识(actionId)
        CloseCallBack closeCallBack = new CloseCallBack(this, "taskcloseback");
        // 1、发布任务，并显示进度,带有前台参数 但是前台窗口会一直等待进度
        //JobForm.dispatch(jobInfo, this.getView(), closeCallBack);
        //2、后台发布任务，前台不见，无法直接感知进度
        //JobClient.dispatch(jobInfo);


        // 3、创建任务进度界面参数、可以切换显示进度状态
        JobFormInfo jobFormInfo = new JobFormInfo(jobInfo);
        jobFormInfo.setCaption("测试任务的执行"); // 进度界面标题
        jobFormInfo.setCloseCallBack(closeCallBack); // 任务完成后的回调处理
        jobFormInfo.setCanBackground(true); // 允许切换到后台执行
        jobFormInfo.setCanStop(true); // 允许中途取消
        jobFormInfo.setClickClassName("kded.demo.schedule.MyTaskClick"); // 切换后台执行后，用户点击后台任务图标，点击事件处理
        // 发布任务，并显示进度
        JobForm.dispatch(jobFormInfo, this.getView());



    }

    /**
     * 任务完成后的回调处理
     *
     * @param returnData
     */
    private void taskCallBack(Object returnData) {
        if (returnData == null) {
            return;
        }

        if (returnData instanceof Map<?, ?>) {
            @SuppressWarnings("unchecked")
            Map<String, Object> result = (Map<String, Object>)returnData;
            if (result.containsKey("taskinfo")) {
                String taskInfoStr = (String)result.get("taskinfo");
                if (StringUtils.isNotBlank(taskInfoStr)) {
                    TaskInfo taskInfo = SerializationUtils.fromJsonString(taskInfoStr, TaskInfo.class);

                    if (taskInfo.isTaskEnd()) {
                        // 获取任务执行完毕，生成的内容
                        String data = taskInfo.getData();
                        this.getView().showMessage(data);
                    }
                }
            }
        }
    }
}